'use client';

import {
  type ChangeEvent,
  type FormEvent,
  useContext,
  useEffect,
  useState,
} from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import diff from 'microdiff';
import type { IDifference, IUpdateJwtConfigBody } from '@/interfaces';
import { IConfigJwt } from '@/interfaces';
import type { TBody } from '@/types';
import { updateJwtConfig } from '@/services/api';
import { useRouter } from 'next/navigation';
import useToast from '@/hooks/useToast';
import { ConfigAdminContext } from '@/contexts/admin/config';
import { getDiffData, getFilterData, isEmpty } from '@/lib/tool';

export default function UpdateConfigJwt({ details }: { details: IConfigJwt }) {
  const { show } = useToast();
  const router = useRouter();
  const [form, setForm] = useState<{
    tokenExp: string;
    refreshTokenExp: string;
    generateNewKey?: boolean;
  }>({
    tokenExp: '',
    refreshTokenExp: '',
    generateNewKey: false,
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const queryClient = useQueryClient();
  const context = useContext(ConfigAdminContext);

  const updateJwtConfigMutation = useMutation(
    async (variables: TBody<IUpdateJwtConfigBody>) => {
      await updateJwtConfig(variables);
      await queryClient.invalidateQueries([
        '/configs',
        `/${context.updateItem?.id}`,
      ]);
    },
  );

  useEffect(() => {
    if (details) {
      setForm({
        tokenExp: details.tokenExp.substring(2) || '',
        refreshTokenExp: details.refreshTokenExp.substring(2) || '',
        generateNewKey: false,
      });
    }
  }, [details]);
  useEffect(() => {
    if (details) {
      const differences = diff(
        {
          tokenExp: details.tokenExp.substring(2) || '',
          refreshTokenExp: details.refreshTokenExp.substring(2) || '',
          generateNewKey: false,
        },
        {
          tokenExp: form.tokenExp || '',
          refreshTokenExp: form.refreshTokenExp || '',
          generateNewKey: form.generateNewKey,
        },
      );
      setDifferenceData(differences);
    }
  }, [form, details]);

  function onChangeForm(e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'generateNewKey') {
      setForm({ ...form, generateNewKey: value === 'true' });
    } else {
      setForm({ ...form, [name]: value.trim().toUpperCase() });
    }
  }

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      checkForm();
      const body = getFilterData(getDiffData(differenceData));
      if (isEmpty(body)) {
        show({
          type: 'SUCCESS',
          message: '保存完成',
        });
        return;
      }

      await updateJwtConfigMutation.mutateAsync({
        data: {
          ...body,
          tokenExp: body.tokenExp ? 'PT' + body.tokenExp : undefined,
          refreshTokenExp: body.refreshTokenExp
            ? 'PT' + body.refreshTokenExp
            : undefined,
        },
      });

      clearData();
      if (typeof body.generateNewKey === 'boolean' && body.generateNewKey) {
        setTimeout(() => {
          show({
            type: 'SUCCESS',
            message: '即将跳转到登录页',
          });
        }, 1000);

        setTimeout(async () => {
          await router.push('/login');
        }, 1500);
      }
    } catch (e) {
      updateJwtConfigMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function clearData() {
    setDifferenceData([]);
  }

  function checkForm() {
    const { tokenExp, refreshTokenExp } = form;

    if (
      !(
        !tokenExp.includes('H') ||
        !tokenExp.includes('M') ||
        !tokenExp.includes('S')
      )
    ) {
      throw '令牌有效期无效';
    }

    if (
      !(
        !refreshTokenExp.includes('H') ||
        !refreshTokenExp.includes('M') ||
        !refreshTokenExp.includes('S')
      )
    ) {
      throw '刷新令牌有效期无效';
    }
  }

  return (
    <div className="row">
      <div className="col">
        <form onSubmit={onClickSave} className="vstack gap-4">
          <div>
            <label className="form-label">
              令牌有效期
              <span className="text-muted">（H 小时，M 分钟，S 秒）</span>
            </label>
            <input
              type="text"
              className="form-control"
              name="tokenExp"
              value={form.tokenExp}
              onChange={onChangeForm}
              aria-describedby="tokenExp"
              placeholder="请输入令牌有效期"
            />
          </div>

          <div>
            <label className="form-label">
              刷新令牌有效期
              <span className="text-muted">（H 小时，M 分钟，S 秒）</span>
            </label>
            <input
              type="text"
              className="form-control"
              name="refreshTokenExp"
              value={form.refreshTokenExp}
              onChange={onChangeForm}
              aria-describedby="refreshTokenExp"
              placeholder="请输入刷新令牌有效期"
            />
          </div>

          <div>
            <label className="form-label">生成新令牌密钥</label>
            <select
              name="generateNewKey"
              value={form.generateNewKey ? 'true' : 'false'}
              onChange={onChangeForm}
              className="form-select"
              aria-label="generateNewKey"
              placeholder="请选择是否生成新令牌密钥"
            >
              <option value="true">true</option>
              <option value="false">false</option>
            </select>
          </div>

          <button
            type="submit"
            disabled={updateJwtConfigMutation.isLoading}
            className="btn btn-success w-25 my-4"
          >
            {updateJwtConfigMutation.isLoading && (
              <span
                className="spinner-border spinner-border-sm me-2"
                role="status"
                aria-hidden="true"
              ></span>
            )}
            更新
          </button>
        </form>
      </div>
    </div>
  );
}
